package org.company.venus.ibatis.dao;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.sql.SQLException;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.ibatis.sqlmap.client.SqlMapClient;

@Repository
@SuppressWarnings("rawtypes")
public abstract class BaseDao<T extends Serializable> {
    
    @Autowired
    private SqlMapClient sqlMapClient;
    
    public SqlMapClient getSqlMapClient() {
        return sqlMapClient;
    }

    public void setSqlMapClient(SqlMapClient sqlMapClient) {
        this.sqlMapClient = sqlMapClient;
    }

    public static final String SELECT = "select";
    
    public static final String INSERT = "insert";
    
    public static final String UPDATE = "update";
    
    public static final String DELETE = "delete";
    
    /**
     * 生成sqlMap的名称,
     * @example SensitivePODao extends BaseDao<SensitivePO>,simpleName="insert" ==> SensitivePO.insert
     * @method getSqlMapStatement
     * @param simpleName
     * @return
     */
    protected final String getSqlMapStatement(T t,String simpleName) {
        return t.getClass().getSimpleName() + "." + simpleName;
    }
    
    /**
     * 返回单个对象，建议通过主键查询
     * @method load
     * @param t
     * @return
     * @throws SQLException
     */
    @SuppressWarnings("unchecked")
    public final T load(T t) throws SQLException {
        return (T)this.getSqlMapClient().queryForObject(getSqlMapStatement(t,SELECT), t);
    }
    
    /**
     * 插入数据
     * @method insert
     * @param t
     * @return
     * @throws SQLException
     */
    @SuppressWarnings("unchecked")
    public final T insert(T t) throws SQLException {
        return (T)this.getSqlMapClient().insert(getSqlMapStatement(t,INSERT), t);
    }
    
    /**
     * 更新数据
     * @method update
     * @param t
     * @return
     * @throws SQLException
     */
    public final Integer update(T t) throws SQLException {
        return this.getSqlMapClient().update(getSqlMapStatement(t,UPDATE), t);
    }
    
    /**
     * 删除数据
     * @method delete
     * @param t
     * @return
     * @throws SQLException
     */
    public final Integer delete(T t) throws SQLException {
        return this.getSqlMapClient().delete(getSqlMapStatement(t,DELETE),t);
    }
    
    /**
     * 查询数据，返回List<T extends Serializable>集合
     * @method query
     * @param t
     * @return
     * @throws SQLException
     */
    @SuppressWarnings("unchecked")
    public final List<T> query(T t) throws SQLException {
        return this.getSqlMapClient().queryForList(getSqlMapStatement(t,SELECT), t);
    }
    
    /**
     * 批量插入
     * @method batchInsert
     * @param list
     * @throws SQLException
     * @see {@link BaseDao#insert(Serializable)}
     */
    public final void batchInsert(List<T> list) throws SQLException {
        this.getSqlMapClient().startBatch();
        for(int i = 0 ; i < list.size() ; i++) {
            this.insert(list.get(i));
        }
        this.getSqlMapClient().executeBatch();
    }
    
    /**
     * 批量删除
     * @method batchDelete
     * @param list
     * @throws SQLException
     * @see {@link BaseDao#delete(Serializable)}
     */
    public final void batchDelete(List<T> list) throws SQLException {
        this.getSqlMapClient().startBatch();
        for(int i=0 ; i < list.size() ; i++) {
            this.delete(list.get(i));
        }
        this.getSqlMapClient().executeBatch();
    }
    
    /**
     * 批量更新
     * @method batchUpdate
     * @param list
     * @throws SQLException
     * @see {@link BaseDao#update(Serializable)}
     */
    public final void batchUpdate(List<T> list) throws SQLException {
        this.getSqlMapClient().startBatch();
        for(int i=0 ; i < list.size() ; i++) {
            this.update(list.get(i));
        }
        this.getSqlMapClient().executeBatch();
    }
}
